home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Dev / ACE_Prgs.lha / games / TallyHo.lha / TallyHo!.b next >
Text File  |  1994-02-12  |  26KB  |  612 lines

  1. '===========================================================================
  2. '
  3. '    %MODULE                   TallyHo!.b
  4. '    %CREATION DATE            01-Feb-1994
  5. '    %PROGRAMMER               Dennis Schank
  6. '    %VERSION                  V1.1
  7. '
  8. '
  9. '    %ABSTRACT  A game in which the number of moves you make upon a grid
  10. '               is determined by the value of the square selected with the
  11. '               mouse.  The path you have already taken cannot be crossed
  12. '               and the attempt to do so will end the game.
  13. '
  14. '
  15. '    %MODIFICATION HISTORY
  16. '           V1.1  05-Feb-1994     Fixed bug that caused cursor to overlap
  17. '                                 onto used blocks on WB screens of 4 or 8
  18. '                                 colors.  [ds]
  19. '
  20. '           V1.0  01-Feb-1994     First written   [ds]
  21. '
  22. '===========================================================================
  23.  
  24.     'Set traps
  25.   ON MENU GOSUB Menu_Option_Selected
  26.   MENU ON
  27.   ON MOUSE GOSUB Mouse_Button_Pushed
  28.   MOUSE ON
  29.   ON WINDOW GOSUB ShutDown
  30.   WINDOW ON
  31.  
  32.     'Includes
  33.   #INCLUDE <longval.h>  'Allow the conversion of strings containing long values (replaces VAL function)
  34.   #INCLUDE <font.h>     'Allows the changing of fonts
  35.   FONTSET("XEN",9)      'Set to a font that will allow more characters per inch
  36.  
  37.     'String declarations
  38.   STRING WindowTitle$ SIZE 80   'Holds string to display on window title bar
  39.   STRING TopTen_File$ SIZE 20   'Holds name of file to store high scores
  40.   STRING Player$ SIZE 80        'Holds name of player if a top ten score is achieved
  41.   STRING TopTenTitle$ SIZE 40   'Holds the string to be displayed at top of top ten list
  42.  
  43.     'Define Constants
  44.   CONST _ROWS = 13, _COLS = 56      'Blocks displayed on screen
  45.  
  46.     'Set all integer variables to type short
  47.   DEFINT a-z
  48.  
  49.     'Override DEFINT for integer variables that need to be other than short
  50.   SINGLE CurrentScore   'Holds the current score displayed on screen
  51.   SINGLE Tally          'Holds the button value as it is used
  52.   SINGLE Bonus          'Holds the bonus value for each mode
  53.  
  54.     'Define arrays
  55.   DIM TopTenName$(10) SIZE 31       'Names of top ten scorers
  56.   DIM TopTenScore$(10) SIZE 12      'Scores of top ten scorers
  57.   DIM TopTenValChk$(10) SIZE 20     'Holds validity check number of high scores
  58.   DIM Grid(_COLS,_ROWS)             'Holds the values of the blocks on the grid
  59.  
  60.     'Open main window
  61.   LET WindowTitle$ = "TallyHo!          Version 1.1  copyright " + CHR$(169) + " 1994 by Dennis Schank"
  62.   WINDOW 1,WindowTitle$,(0,14)-(635,214),30
  63.   WINDOW OUTPUT 1
  64.   FONTSET("XEN",9)      'Set to a font that will allow more characters per inch
  65.  
  66.  
  67.     'Make menus    -    Place 10 spaces at end of longest menu item for each menu that has quick keys
  68.         'Menu 1
  69.   MENU 1,0,1,"Options    "
  70.   MENU 1,1,1," View Scores          ","V"
  71.   MENU 1,2,1," Help","H"
  72.   MENU 1,3,1," About","A"
  73.   MENU 1,4,1," Quit","Q"
  74.         'Menu 2
  75.   MENU 2,0,1,"Play    "
  76.   MENU 2,1,1," New Game","G"
  77.   MENU 2,2,1," End Current Game          ","E"
  78.         'Menu 3
  79.   MENU 3,0,1,"Mode    "
  80.   MENU 3,1,1,"       Beginner"
  81.   MENU 3,2,2,"       Casual Player"
  82.   MENU 3,3,1,"       Crazed Fanatic "
  83.  
  84.  
  85. ' ====   Set coordinates  ====
  86.  
  87.     'Button coordinates
  88.   LET ButtonX = 6       'x coordinate to start first button (top left corner)
  89.   LET ButtonY = 9       'y coordinate to start first button (top left corner)
  90.   LET BtnHeight = 10    'Height of buttons in pixels
  91.   LET BtnWidth = 10     'Width of buttons in pixels
  92.  
  93.     'Score Box coordinates
  94.   LET ScoreBoxX = 220   'x coordinate for the score box (top left corner)
  95.   LET ScoreBoxY = 160   'y coordinate for the score box (top left corner)
  96.   LET SBoxWidth = 200   'Width of scorebox in pixels
  97.   LET SBoxHeight = 16   'Height of scorebox in pixels
  98.  
  99.  
  100. ' ====  Begin main routine  ====
  101.  
  102.  
  103.     'Set default values
  104.   LET Mode_Block_Value = 6              'Maximum value for blocks in Casual Player mode
  105.   LET Mode_Bonus_Value = 7000           'Bonus given for each block used in Casual Player mode
  106.   LET TopTen_File$ = "TH!_TopTen_CP"    'File to save top ten scores in Casual Player mode
  107.   LET Mode = 2                          'Mode flag (1=Beginner, 2=Casual Player, 3=Crazed Fanatic)
  108.  
  109.   GOSUB Load_TopTen
  110.  
  111.   RANDOMIZE TIMER   'Makes sure that there is a different set of random numbers each time run
  112.   GOSUB New_Game
  113.  
  114.  
  115. '  +==================================+
  116. '  |  Wait for mouse or menu activity |
  117. '  +==================================+
  118.  
  119.   WHILE -1
  120.     SLEEP
  121.   WEND
  122.  
  123.  
  124.  
  125. '  +===============+
  126. '  |  SUBROUTINES  |
  127. '  +===============+
  128.  
  129. '  ---- Initialize Variables  ----
  130.  
  131. Initialize_Variables:
  132.   LET GameOver = 0                              'Set to FALSE
  133.   LET ScoreNotChecked = -1                      'Set to TRUE
  134.   LET Tally = 0                                 'Initialize running score variable
  135.   LET OriginalX = INT(RND*_COLS)+1              'Randomly select cursor start x on grid
  136.   LET OriginalY = INT(RND*_ROWS)+1              'Randomly select cursor start y on grid
  137.   LET CurrentX = OriginalX                      'Set current position x to cursor position x
  138.   LET CurrentY = OriginalY                      'Set current position y to cursor position y
  139.   LET CurrentScore = Grid(CurrentX,CurrentY)    'Start score at value of starting block
  140.   RETURN
  141.  
  142.  
  143. '  ----  Load top ten scores  ----
  144.  
  145. Load_TopTen:
  146.   OPEN "I",#1,TopTen_File$
  147.   FOR s = 1 TO 10
  148.     IF EOF(1) THEN          'Initialize all scores if file does not exist
  149.       LET TopTenScore$(s) = "10000"
  150.       LET TopTenName$(s) = "TallyHo!"
  151.       LET TopTenValChk$(s) = STR$(SIN(ASC(TopTenName$(s)) + LONGVAL&(MID$(TopTenScore$(s),2,3))))
  152.     ELSE
  153.       INPUT #1,TopTenScore$(s),TopTenName$(s),TopTenValChk$(s)
  154.         'Check to see if file has been tampered with
  155.       IF STR$(SIN(ASC(TopTenName$(s)) + LONGVAL&(MID$(TopTenScore$(s),2,3)))) <> TopTenValChk$(s) THEN
  156.         LET i = MSGBOX("TOP TEN file is corrupt...A new file will be created.","Confirm")
  157.         FOR i = 1 TO 10
  158.           LET TopTenScore$(i) = "10000"
  159.           LET TopTenName$(i) = "TallyHo!"
  160.           LET TopTenValChk$(i) = STR$(SIN(ASC(TopTenName$(i)) + LONGVAL&(MID$(TopTenScore$(i),2,3))))
  161.         NEXT i
  162.         LET s = 10
  163.       END IF
  164.     END IF
  165.   NEXT s
  166.   CLOSE #1
  167.   RETURN
  168.  
  169.  
  170. '  ----  Display new game stuff  ----
  171.  
  172. New_Game:
  173.   MENU 2,2,1    'Enable "End Current Game" menu option
  174.   CLS           'Clear screen
  175.     'Display the score box
  176.   LINE (ScoreBoxX,ScoreBoxY)-(ScoreBoxX+SBoxWidth,ScoreBoxY),2
  177.   LINE (ScoreBoxX,ScoreBoxY)-(ScoreBoxX,ScoreBoxY+SBoxHeight),2
  178.   LINE (ScoreBoxX+SBoxWidth,ScoreBoxY+SBoxHeight)-(ScoreBoxX+SBoxWidth,ScoreBoxY),1
  179.   LINE (ScoreBoxX+SBoxWidth,ScoreBoxY+SBoxHeight)-(ScoreBoxX,ScoreBoxY+SBoxHeight),1
  180.   LINE (ScoreBoxX+(INT(SBoxWidth/2)),ScoreBoxY+2)-(ScoreBoxX+(SBoxWidth-6),ScoreBoxY+2),1
  181.   LINE (ScoreBoxX+(INT(SBoxWidth/2)),ScoreBoxY+2)-(ScoreBoxX+(INT(SBoxWidth/2)),ScoreBoxY+(SBoxHeight-2)),1
  182.   LINE (ScoreBoxX+(SBoxWidth-2),ScoreBoxY+(SBoxHeight-2))-(ScoreBoxX+(SBoxWidth-2),ScoreBoxY+2),2
  183.   LINE (ScoreBoxX+(SBoxWidth-2),ScoreBoxY+(SBoxHeight-2))-(ScoreBoxX+(INT(SBoxWidth/2)),ScoreBoxY+(SBoxHeight-2)),2
  184.   PENUP
  185.   SETXY ScoreBoxX+INT(SBoxWidth/5),ScoreBoxY+(2*INT(SBoxHeight/3))
  186.   PRINT "SCORE";
  187.     'Create the grid buttons with values in them
  188.   LET RowNum = 0
  189.   FOR y = ButtonY TO ((BtnHeight+1)*(_ROWS-1))+ButtonY STEP BtnHeight+1
  190.     ++RowNum
  191.     LET ColNum = 0
  192.     FOR x = ButtonX TO ((BtnWidth+1)*(_COLS-1))+ButtonX STEP BtnWidth+1
  193.       ++ColNum
  194.       LINE (x,y)-(x+BtnWidth,y),2                       'TOP
  195.       LINE (x,y)-(x,y+BtnHeight),2                      'LEFT
  196.       LINE (x+BtnWidth,y+BtnHeight)-(x+BtnWidth,y),1   'RIGHT
  197.       LINE (x+BtnWidth,y+BtnHeight)-(x,y+BtnHeight),1  'BOTTOM
  198.       LET BtnValue = INT(RND*Mode_Block_Value)+1    'Randomly set button value
  199.       LET Grid(ColNum,RowNum) = BtnValue            'Assign value to corresponding grid array position
  200.       PENUP
  201.       SETXY x+3,y+(BtnHeight-3)
  202.       PRINT RIGHT$(STR$(BtnValue),1);       'Print value in button after removing leading space
  203.     NEXT x
  204.   NEXT y
  205.   GOSUB Initialize_Variables
  206.     'Determine the top left pixel of the starting position of the cursor
  207.   LET CurrentBtnX = ((BtnWidth+1)*(CurrentX-1))+ButtonX
  208.   LET CurrentBtnY = ((BtnHeight+1)*(CurrentY-1))+ButtonY
  209.     'Give cursor block illusion of being pressed in
  210.   LINE (CurrentBtnX,CurrentBtnY)-(CurrentBtnX+BtnWidth,CurrentBtnY),1
  211.   LINE (CurrentBtnX,CurrentBtnY)-(CurrentBtnX,CurrentBtnY+BtnHeight),1
  212.   LINE (CurrentBtnX+BtnWidth,CurrentBtnY+BtnHeight)-(CurrentBtnX+BtnWidth,CurrentBtnY),2
  213.   LINE (CurrentBtnX+BtnWidth,CurrentBtnY+BtnHeight)-(CurrentBtnX,CurrentBtnY+BtnHeight),2
  214.     'Color the cursor block
  215.   LINE (CurrentBtnX+1,CurrentBtnY+1)-(CurrentBtnX+BtnWidth-1,CurrentBtnY+BtnHeight-1),11,BF
  216.   PENUP
  217.   SETXY 4+(ScoreBoxX+INT(SBoxWidth/2)),ScoreBoxY+(2*INT(SBoxHeight/3))
  218.   PRINT CurrentScore;" "    'Print the starting score in scorebox
  219.   RETURN
  220.  
  221.  
  222. '  ----  Tally the score if valid move  ----
  223.  
  224. Tally_It:
  225.   MENU 2,1,0    'Disable "New Game" menu option to avoid accidental loss of accumulated score
  226.   MENU 3,0,0    'Disable "Mode" menu so user must end the game in order to change mode
  227.   LET Tally = Grid(CurrentX,CurrentY)   'Get value of block clicked on
  228.     'Determine which direction movement is being made
  229.   IF CurrentX < OriginalX THEN
  230.     LET DestinyX = OriginalX - Tally
  231.   ELSE
  232.     IF CurrentX > OriginalX THEN
  233.       LET DestinyX = OriginalX + Tally
  234.     ELSE
  235.       LET DestinyX = OriginalX
  236.     END IF
  237.   END IF
  238.   IF CurrentY < OriginalY THEN
  239.     LET DestinyY = OriginalY - Tally
  240.   ELSE
  241.     IF CurrentY > OriginalY THEN
  242.       LET DestinyY = OriginalY + Tally
  243.     ELSE
  244.       LET DestinyY = OriginalY
  245.     END IF
  246.   END IF
  247.   LET Tally = 0
  248.   LET Bonus = 0
  249.     'Tally up the values of the blocks used
  250.   FOR b = 1 TO Mode_Block_Value     'Repeats for maximum possible moves
  251.       'Determine the top left pixel of the starting position of the cursor
  252.     LET CurrentBtnX = ((BtnWidth+1)*(CurrentX-1))+ButtonX
  253.     LET CurrentBtnY = ((BtnHeight+1)*(CurrentY-1))+ButtonY
  254.      'Check to see if path is crossed
  255.     IF Grid(CurrentX,CurrentY) = 0 THEN
  256.         'Stop cursor in current block and color it because path was crossed
  257.       LINE (CurrentBtnX+1,CurrentBtnY+1)-(CurrentBtnX+BtnWidth-1,CurrentBtnY+BtnHeight-1),8,BF
  258.         'Clear original cursor location
  259.       LET OriginalBtnX = ((BtnWidth+1)*(OriginalX-1))+ButtonX
  260.       LET OriginalBtnY = ((BtnHeight+1)*(OriginalY-1))+ButtonY
  261.       LINE (OriginalBtnX+1,OriginalBtnY+1)-(OriginalBtnX+BtnWidth-1,OriginalBtnY+BtnHeight-1),0,BF
  262.       BEEP
  263.         'Inform player that game is over
  264.       LET GameOver = MSGBOX("You have crossed your previous path.  -  GAME OVER","OK")
  265.       GOSUB Check_Score             'See if score is in top ten
  266.       GOSUB Show_TopTen             'Display the top ten list
  267.       MENU 2,1,1                    'Enable "New Game" menu option
  268.       MENU 2,2,0                    'Disable "End Current Game" menu option
  269.       MENU 3,0,1                    'Enable "Mode" menu
  270.       LET b = Mode_Block_Value      'Set value of b to last iteration of loop
  271.       GOTO PathFinished             'Go to the end of the loop so exit will be performed
  272.     END IF
  273.       'Since path was not crossed, give current position illustion of being pressed
  274.     LINE (CurrentBtnX,CurrentBtnY)-(CurrentBtnX+BtnWidth,CurrentBtnY),1
  275.     LINE (CurrentBtnX,CurrentBtnY)-(CurrentBtnX,CurrentBtnY+BtnHeight),1
  276.     LINE (CurrentBtnX+BtnWidth,CurrentBtnY+BtnHeight)-(CurrentBtnX+BtnWidth,CurrentBtnY),2
  277.     LINE (CurrentBtnX+BtnWidth,CurrentBtnY+BtnHeight)-(CurrentBtnX,CurrentBtnY+BtnHeight),2
  278.       'Give tentative points for block used
  279.     LET Bonus = Bonus + Mode_Bonus_Value
  280.     LET Tally = Tally + Grid(CurrentX,CurrentY)
  281.       'Set value of block to zero so it can be checked later for overlap
  282.     LET Grid(CurrentX,CurrentY) = 0
  283.       'Check to see if the range of moves have been made
  284.     IF CurrentX = DestinyX AND CurrentY = DestinyY THEN
  285.         'Stop cursor in current block and color it because range of moves complete
  286.       LINE (CurrentBtnX+1,CurrentBtnY+1)-(CurrentBtnX+BtnWidth-1,CurrentBtnY+BtnHeight-1),11,BF
  287.         'Clear original cursor location
  288.       LET OriginalBtnX = ((BtnWidth+1)*(OriginalX-1))+ButtonX
  289.       LET OriginalBtnY = ((BtnHeight+1)*(OriginalY-1))+ButtonY
  290.       LINE (OriginalBtnX+1,OriginalBtnY+1)-(OriginalBtnX+BtnWidth-1,OriginalBtnY+BtnHeight-1),0,BF
  291.         'Make current location the original to prepare for player's next move
  292.       LET OriginalX = CurrentX
  293.       LET OriginalY = CurrentY
  294.         'Give 100 times the value of all used blocks and add bonus
  295.       LET Tally = (Tally * 100) + Bonus
  296.         'Add tentative score to current score and display
  297.       LET CurrentScore = CurrentScore + Tally
  298.       PENUP
  299.       SETXY 4+(ScoreBoxX+INT(SBoxWidth/2)),ScoreBoxY+(2*INT(SBoxHeight/3))
  300.       PRINT CurrentScore;" "
  301.       LET b = Mode_Block_Value      'Set value of b to last iteration of loop
  302.       GOTO PathFinished             'Go to the end of the loop so exit will be performed
  303.     ELSE
  304.         'Since range of moves not complete, just clear the button text
  305.       LINE (CurrentBtnX+1,CurrentBtnY+1)-(CurrentBtnX+BtnWidth-1,CurrentBtnY+BtnHeight-1),0,BF
  306.     END IF
  307.       'Increment or decrement values of cursor on grid in accordance to direction of original move
  308.     IF DestinyX < OriginalX THEN --CurrentX
  309.     IF DestinyX > OriginalX THEN ++CurrentX
  310.     IF DestinyY < OriginalY THEN --CurrentY
  311.     IF DestinyY > OriginalY THEN ++CurrentY
  312.       'Check to see if cursor is beyond the edge of the grid
  313.     IF CurrentX < 1 OR CurrentX > _COLS OR CurrentY < 1 OR CurrentY > _ROWS THEN
  314.         'Since edge of grid was reached move cursor back to last position on grid
  315.       IF DestinyX < OriginalX THEN ++CurrentX
  316.       IF DestinyX > OriginalX THEN --CurrentX
  317.       IF DestinyY < OriginalY THEN ++CurrentY
  318.       IF DestinyY > OriginalY THEN --CurrentY
  319.         'Stop cursor in current block and color it because range of moves complete
  320.       LINE (CurrentBtnX+1,CurrentBtnY+1)-(CurrentBtnX+BtnWidth-1,CurrentBtnY+BtnHeight-1),11,BF
  321.         'Clear original cursor location
  322.       LET OriginalBtnX = ((BtnWidth+1)*(OriginalX-1))+ButtonX
  323.       LET OriginalBtnY = ((BtnHeight+1)*(OriginalY-1))+ButtonY
  324.       LINE (OriginalBtnX+1,OriginalBtnY+1)-(OriginalBtnX+BtnWidth-1,OriginalBtnY+BtnHeight-1),0,BF
  325.         'Make current location the original to prepare for player's next move
  326.       LET OriginalX = CurrentX
  327.       LET OriginalY = CurrentY
  328.         'Give 100 times the value of all used blocks and add bonus
  329.       LET Tally = (Tally * 100) + Bonus
  330.         'Add tentative score to current score and display
  331.       LET CurrentScore = CurrentScore + Tally
  332.       PENUP
  333.       SETXY 4+(ScoreBoxX+INT(SBoxWidth/2)),ScoreBoxY+(2*INT(SBoxHeight/3))
  334.       PRINT CurrentScore;" "
  335.       LET b = Mode_Block_Value      'Set value of b to last iteration of loop
  336.     END IF
  337. PathFinished:
  338.   NEXT b
  339.   RETURN
  340.  
  341.  
  342. '  ----  Check to see if score is in top ten  ----
  343. Check_Score:
  344.     'See if score is greater than lowest top ten score
  345.   IF CurrentScore > LONGVAL&(TopTenScore$(10)) THEN
  346.       'Player made top ten so prompt for name
  347.     LET Player$ = LEFT$(INPUTBOX$("Please enter your name:","You made the TOP TEN scores list.",Player$),65)
  348.       'Determine which position player belongs in
  349.     FOR s = 1 TO 10
  350.       IF CurrentScore > LONGVAL&(TopTenScore$(s)) THEN
  351.           { Since the players score is larger than the person currently in this position,
  352.             go to the end of the array and move everyone down one.
  353.           }
  354.         FOR c = 10 TO s+1 STEP -1
  355.           LET TopTenScore$(c) = TopTenScore$(c-1)
  356.           LET TopTenName$(c) = TopTenName$(c-1)
  357.           LET TopTenValChk$(c) = TopTenValChk$(c-1)
  358.         NEXT c
  359.           'Now put player in place of last person moved down
  360.         LET TopTenScore$(s) = STR$(CurrentScore)
  361.         LET TopTenName$(s) = Player$
  362.           { Take the ascii value of the first character of the player's name, add it to
  363.             the first three digits of the score, and return the SINE of the total as the
  364.             validity check for the purpose of checking for tampering of high scores.
  365.           }
  366.         LET TopTenValChk$(s) = STR$(SIN(ASC(TopTenName$(s)) + LONGVAL&(MID$(STR$(CurrentScore),2,3))))
  367.         LET s = 10
  368.       END IF
  369.     NEXT s
  370.     GOSUB Write_High_Scores     'Write the current list of high scores to output file
  371.   END IF
  372.   LET ScoreNotChecked = 0       'Set to FALSE
  373.   RETURN
  374.  
  375.  
  376. '  ----  Display the top ten list  ----
  377.  
  378. Show_TopTen:
  379.     'Open new window to display scores
  380.   WINDOW 2,"TallyHo! TOP TEN scores...",(30,25)-(605,188),24
  381.   WINDOW OUTPUT 2
  382.   FONTSET("XEN",9)      'Set to a font that will allow more characters per inch
  383.   PRINT ""
  384.     'Determine what tile to display at top of listing and print it
  385.   IF Mode = 1 THEN LET TopTenTitle$ = " Top Ten Scores for Beginner Mode"
  386.   IF Mode = 2 THEN LET TopTenTitle$ = "Top Ten Scores for Casual Player Mode"
  387.   IF Mode = 3 THEN LET TopTenTitle$ = "Top Ten Scores for Crazed Fanatic Mode"
  388.   PRINT STRING$(27," ");TopTenTitle$
  389.   PRINT ""
  390.     'Display all scores
  391.   FOR s = 1 TO 10
  392.     IF s < 10 THEN PRINT " ";
  393.     PRINT "   ";STR$(s);"  ";LEFT$(TopTenName$(s) + STRING$(67,"."),67);STRING$(10 - LEN(TopTenScore$(s)),".");TopTenScore$(s)
  394.   NEXT s
  395.   PRINT ""
  396.   PRINT ""
  397.   INPUT "                                  Press [ENTER] to exit...     ",s
  398.   WINDOW CLOSE 2
  399.   WINDOW OUTPUT 1
  400.   RETURN
  401.  
  402.  
  403. '  ----  Display HELP  ----
  404.  
  405. Display_Help:
  406.     'Open new window to display help
  407.   WINDOW 3,"TallyHo! - HELP",(0,14)-(635,214),24
  408.   WINDOW OUTPUT 3
  409.   FONTSET("XEN",9)      'Set to a font that will allow more characters per inch
  410.     'Display help information
  411.   PRINT ""
  412.   PRINT ""
  413.   PRINT "   TallyHo! is a simple game in which the object is to move upon a grid of numbers to tally up"
  414.   PRINT "   the highest score possible.  This is accomplished by clicking the mouse pointer on a number"
  415.   PRINT "   block that is adjacent to the block occupied by the colored cursor.  The number you click on"
  416.   PRINT "   determines how far the cursor will move.  The exception is if there is not enough blocks to"
  417.   PRINT "   finish the range of moves before the cursor reaches the edge of the grid.  In this case, the"
  418.   PRINT "   cursor stops when it reaches the edge.  The game ends when the cursor enters a block that has"
  419.   PRINT "   already been used.  If you have no more valid moves, select End Current Game from the Play"
  420.   PRINT "   menu or force the cursor into a used block so your score can be checked against high scores."
  421.   PRINT ""
  422.   PRINT "   The block values are selected randomly as is the start position of the cursor.   You may move"
  423.   PRINT "   in any direction from the cursor (left, right, up, down, diagonal).  The score is calculated by"
  424.   PRINT "   giving you 100 times the value of each block used plus additional bonus points for each block"
  425.   PRINT "   used.  The values of the blocks will range from 1 to 4 in Beginner mode, 1 to 6 in Casual Player"
  426.   PRINT "   mode, and 1 to 9 in Crazed Fanatic mode.  The bonus points given for each block used is 5,000 in"
  427.   PRINT "   Beginner mode, 7,000 in Casual Player mode, and 10,000 in Crazed Fanatic mode.  Casual Player"
  428.   PRINT "   mode is the default.    HAVE FUN!"
  429.   PRINT ""
  430.   PRINT ""
  431.   INPUT "                                       Press [ENTER] to exit...     ",s
  432.   WINDOW CLOSE 3
  433.   WINDOW OUTPUT 1
  434.   RETURN
  435.  
  436.  
  437. '  ----  Change the mode  ----
  438.  
  439. Change_Mode:
  440.   LET ModeChanged = 0       'Set to FALSE
  441.   IF MenuItem = 1 AND Mode <> 1 THEN
  442.     MENU 3,1,2                          'Put a checkmark beside "Beginner" menu option
  443.     MENU 3,2,1                          'Take checkmark off of "Casual Player" menu option if exists
  444.     MENU 3,3,1                          'Take checkmark off of "Crazed Fanatic" menu option if exists
  445.     LET Mode_Block_Value = 4            'Maximum value for blocks in Beginner mode
  446.     LET Mode_Bonus_Value = 5000         'Bonus given for each block used in Beginner mode
  447.     LET TopTen_File$ = "TH!_TopTen_B"   'File to save top ten scores in Beginner mode
  448.     LET Mode = 1                        'Mode flag (1=Beginner, 2=Casual Player, 3=Crazed Fanatic)
  449.     LET ModeChanged = 1                 'Set to TRUE
  450.   END IF
  451.   IF MenuItem = 2 AND Mode <> 2 THEN
  452.     MENU 3,1,1                          'Take checkmark off of "Beginner" menu option if exists
  453.     MENU 3,2,2                          'Put a checkmark beside "Casual Player" menu option
  454.     MENU 3,3,1                          'Take checkmark off of "Crazed Fanatic" menu option if exists
  455.     LET Mode_Block_Value = 6            'Maximum value for blocks in Casual Player mode
  456.     LET Mode_Bonus_Value = 7000         'Bonus given for each block used in Casual Player mode
  457.     LET TopTen_File$ = "TH!_TopTen_CP"  'File to save top ten scores in Casual Player mode
  458.     LET Mode = 2                        'Mode flag (1=Beginner, 2=Casual Player, 3=Crazed Fanatic)
  459.     LET ModeChanged = 1                 'Set to TRUE
  460.   END IF
  461.   IF MenuItem = 3 AND Mode <> 3 THEN
  462.     MENU 3,1,1                          'Take checkmark off of "Beginner" menu option if exists
  463.     MENU 3,2,1                          'Take checkmark off of "Casual Player" menu option if exists
  464.     MENU 3,3,2                          'Put a checkmark beside "Crazed Fanatic" menu option
  465.     LET Mode_Block_Value = 9            'Maximum value for blocks in Crazed Fanatic mode
  466.     LET Mode_Bonus_Value = 10000        'Bonus given for each block used in Crazed Fanatic mode
  467.     LET TopTen_File$ = "TH!_TopTen_CF"  'File to save top ten scores in Crazed Fanatic mode
  468.     LET Mode = 3                        'Mode flag (1=Beginner, 2=Casual Player, 3=Crazed Fanatic)
  469.     LET ModeChanged = 1                 'Set to TRUE
  470.   END IF
  471.     'Check to see if mode was changed, if so, load scores for that mode and start a new game
  472.   IF ModeChanged THEN
  473.     GOSUB Load_TopTen
  474.     GOSUB New_Game
  475.   END IF
  476.   RETURN
  477.  
  478.  
  479. '  ----  Show information about TallyHo!  ----
  480.  
  481. Show_About:
  482.     'Open new window to display information about TallyHo!
  483.   WINDOW 4,"About TallyHo!...",(30,30)-(315,190),24
  484.   WINDOW OUTPUT 4
  485.   FONTSET("XEN",9)      'Set to a font that will allow more characters per inch
  486.   PRINT ""
  487.   PRINT ""
  488.   PRINT "  TallyHo!  Version 1.1"
  489.   PRINT "     copyright ";CHR$(169);" February 1994 by"
  490.   PRINT ""
  491.   PRINT "     Dennis Schank"
  492.   PRINT "     1523 N 47th Street"
  493.   PRINT "     Kansas City, KS  66102"
  494.   PRINT "     USA"
  495.   PRINT ""
  496.   PRINT "  Written entirely in ACE-Basic V2.0
  497.   PRINT "    copyright ";CHR$(169);" 1991-1994 by David Benn"
  498.   PRINT ""
  499.   PRINT ""
  500.   INPUT "         Press [ENTER] to exit...    ",s
  501.   WINDOW CLOSE 4
  502.   WINDOW OUTPUT 1
  503.   RETURN
  504.  
  505.  
  506. '  ----  Write the high scores file  ----
  507.  
  508. Write_High_Scores:
  509.       'Open the file for the high scores for given mode and write contest of arrays
  510.     OPEN "O",#1,TopTen_File$
  511.     FOR s = 1 TO 10
  512.       WRITE #1,TopTenScore$(s),TopTenName$(s),TopTenValChk$(s)
  513.     NEXT s
  514.     CLOSE #1
  515.   RETURN
  516.  
  517.  
  518. '  ----  Left mouse button was pushed  ----
  519.  
  520. Mouse_Button_Pushed:
  521.     'Determine which button, if any, was clicked
  522.   IF GameOver THEN RETURN       'Do not allow clicking on buttons if game is not active
  523.   LET SelectedX = 0
  524.   LET SelectedY = 0
  525.     'Check only valid columns (cursor column, 1 left of cursor, 1 right cursor)
  526.   FOR x = CurrentX-1 TO CurrentX+1
  527.     LET CheckX = ((BtnWidth+1)*(x-1))+ButtonX
  528.     IF MOUSE(1) > CheckX AND MOUSE(1) < CheckX+BtnWidth THEN
  529.       LET SelectedX = x
  530.     END IF
  531.   NEXT x
  532.     'Check only valid rows (cursor row, 1 above cursor, 1 below cursor)
  533.   FOR y = CurrentY-1 TO CurrentY+1
  534.     LET CheckY = ((BtnHeight+1)*(y-1))+ButtonY
  535.     IF MOUSE(2) > CheckY AND MOUSE(2) < CheckY+BtnHeight THEN
  536.       LET SelectedY = y
  537.     END IF
  538.   NEXT y
  539.     'Accept only if clicked on block other than block containing cursor
  540.   IF NOT (SelectedX = CurrentX AND SelectedY = CurrentY) THEN
  541.       'Make sure area clicked is within grid boundaries
  542.     IF SelectedX > 0 AND SelectedX <= _COLS AND SelectedY > 0 AND SelectedY <= _ROWS THEN
  543.         'Move current position to that of block clicked
  544.       LET CurrentX = SelectedX
  545.       LET CurrentY = SelectedY
  546.       GOSUB Tally_It            'Make the necessary moves
  547.     END IF
  548.   END IF
  549. Mouse_Return:
  550.     { Do not return until player has released mouse button to avoid unwanted
  551.       selection of blocks due to dragging of mouse.
  552.     }
  553.   WHILE MOUSE(0) = -1
  554.   WEND
  555.   RETURN
  556.  
  557.  
  558. '  ----  Menu option was selected  ----
  559.  
  560. Menu_Option_Selected:
  561.   LET MenuNum = MENU(0)         'Determine which menu selected from
  562.   LET MenuItem = MENU(1)        'Determine which item of the menu selected
  563.     'See if "View Scores" menu item was selected
  564.   IF MenuNum = 1 AND MenuItem = 1 THEN
  565.     GOSUB Show_TopTen
  566.   END IF
  567.     'See if "Help" menu item was selected
  568.   IF MenuNum = 1 AND MenuItem = 2 THEN
  569.     GOSUB Display_Help
  570.   END IF
  571.     'See if "About" menu item was selected
  572.   IF MenuNum = 1 AND MenuItem = 3 THEN
  573.     GOSUB Show_About
  574.   END IF
  575.     'See if "Quit" menu item was selected
  576.   IF MenuNum = 1 AND MenuItem = 4 THEN
  577.     GOSUB ShutDown
  578.   END IF
  579.     'See if "New Game" menu item was selected
  580.   IF MenuNum = 2 AND MenuItem = 1 THEN
  581.     GOSUB New_Game
  582.   END IF
  583.     'See if "End Current Game" menu item was selected
  584.   IF MenuNum = 2 AND MenuItem = 2 THEN
  585.       'Double check player's intentions to avoid losing accumulated score
  586.     LET GameOver = MSGBOX("Are you sure you want to end this game?","What did I just say?","Are you nuts?")
  587.       'See if player did indeed intend to end game
  588.     IF GameOver THEN
  589.       GOSUB Check_Score     'See if player made top ten scores list
  590.       GOSUB Show_TopTen     'Display the top ten scores list
  591.       MENU 2,1,1            'Enable "New Game" menu option
  592.       MENU 2,2,0            'Disable "End Current Game" menu option
  593.       MENU 3,0,1            'Enable "Mode" menu
  594.     END IF
  595.   END IF
  596.     'See if an item was selected from the "Mode" menu
  597.   IF MenuNum = 3 THEN
  598.     GOSUB Change_Mode
  599.   END IF
  600. Menu_Return:
  601.   RETURN
  602.  
  603.  
  604. ShutDown:
  605.   IF ScoreNotChecked THEN
  606.     GOSUB Check_Score
  607.   END IF
  608.   WINDOW CLOSE 1
  609.   STOP              'End the program
  610.     'This RETURN will never be reached  -  It's only purpose is to avoid compiler errors
  611. '  RETURN
  612.